package com.moter.demo01.requirements.re_0905.question_queue;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

public class MoterQueueImpl<T> implements MoterQueue<T>, MoterIterable<T> {

    //锁
    private final Lock putLock = new ReentrantLock();//入队锁
    private final Lock takeLock = new ReentrantLock();//出队锁
    //默认容量
    private final int DEFAULT_CAPACITY = 10;
    
    private int capacity;
    //元素个数
    private AtomicInteger size = new AtomicInteger(0);
    //修改次数
    transient int moterCount;//修改次数，防止，在迭代的时候发生数据变化。
    //头指针
    private Node<T> head = null;
    //尾指针
    private Node<T> tail = null;

    @Override
    public MoterIterator<T> iterator() {
        return new MoterIteratorImpl();
    }

    private class MoterIteratorImpl implements MoterIterator<T> {
        private Node<T> begin = null;
        private Node<T> current = null;//用于remove方法。当前遍历结点
        private int count = moterCount;//用于验证在迭代的时候 数据是否被修改

        public MoterIteratorImpl() {
            begin = head;
        }

        @Override
        public boolean hasNext() {
            return begin != null;
        }

        @Override
        public T next() {
            if (moterCount != count)
                throw new ConcurrentModificationException("迭代的时候被修改了");
            T t = begin.element;
            current = begin;
            begin = begin.next;
            return t;
        }

        @Override
        public void remove() {
            MoterQueueImpl.this.remove(current.element);
            count = moterCount;
        }

    }

    @Override
    public void forEach(Consumer<? super T> consumer) {
        Objects.requireNonNull(consumer);
        Node<T> t = head;
        while (t != null) {
            consumer.accept(t.element);
            t = t.next;
        }
    }

    //结点类结构
    static class Node<T> {
        Node<T> pre;
        Node<T> next;
        T element;

        public Node(Node<T> pre, Node<T> next, T element) {
            this.pre = pre;
            this.next = next;
            this.element = element;
        }
    }

    public MoterQueueImpl() {
        capacity = DEFAULT_CAPACITY;
    }

    public MoterQueueImpl(int capacity) {
        this.capacity = capacity;
    }

    /**
     * 如果容量慢，就抛出异常。
     *
     * @param t
     * @return
     */
    @Override
    public Boolean add(T t) {
        if (isOutOfRange(size.get() + 1))
            throw new IllegalStateException("容量已经到达最大");
        return offer(t);
    }


    @Override
    public Boolean offer(T t) {
        if (isOutOfRange(size.get() + 1))
            return false;
        else {
            putLock.lock();
            try {
                if (size.get() == 0)
                    firstAdd(t);
                else
                    normalAdd(t);
            } finally {
                putLock.unlock();
                return true;
            }
        }
    }

    @Override
    public T poll() {
        if (isEmpty())
            return null;
        T t = null;
        takeLock.lock();
        try {
            t = tail.element;
            if (head == tail) {//如果只有一个元素
                head = null;
                tail = null;
                size.decrementAndGet();
            } else {
                unlinkLast();//删除最后一个结点
            }
        } finally {
            takeLock.unlock();
            return t;
        }
    }

    @Override
    public T remove() {
        if (isEmpty())
            throw new NoSuchElementException("队列为空！");
        return poll();
    }

    @Override
    public T element() {
        if (isEmpty())
            throw new NoSuchElementException("队列为空！");
        return peek();
    }

    @Override
    public T peek() {
        if (isEmpty())
            return null;
        return tail.element;
    }

    //============================工具方法
    private boolean isOutOfRange(int size) {
        return size > capacity;
    }

    public boolean isEmpty() {
        return size.get() == 0;
    }

    private void firstAdd(T t) {
        size.incrementAndGet();
        Node<T> tNode = new Node<>(null, null, t);
        head = tNode;
        tail = tNode;
    }

    private void normalAdd(T t) {
        size.incrementAndGet();
        Node<T> temp = new Node<>(null, null, t);
        head.pre = temp;
        temp.next = head;
        head = temp;
    }

    /**
     * 下面的方法都是删除结点
     *
     * @param t
     */
    public void remove(T t) {
        takeLock.lock();
        try {
            if (head == tail) {
                tail = null;
                head = null;
            } else if (head.element == t) {
                unlinkFirst();
            } else if (tail.element == t) {
                unlinkLast();
            } else {
                unlink(t);
            }
        } finally {
            takeLock.unlock();
        }
    }

    //删除头节点
    private void unlinkFirst() {
        head = head.next;
        head.pre = null;
        moterCount++;
        size.decrementAndGet();
    }

    //删除尾结点
    private void unlinkLast() {
        tail = tail.pre;
        tail.next = null;
        moterCount++;
        size.decrementAndGet();
    }

    //删除中间结点
    private void unlink(T t) {
        Node<T> tempHead = head.next;
        while (tempHead != null) {
            if (tempHead.element == t) {
                tempHead.next.pre = tempHead.pre;
                tempHead.pre.next = tempHead.next;
                moterCount++;
                size.decrementAndGet();
                break;
            }
            tempHead = tempHead.next;
        }
    }
}
